Skip to content

fix: state parallel-region errors, evolution guarded-diff, expr int64, and hot-path allocations#150

Merged
joshua-temple merged 4 commits into
mainfrom
fix/state-correctness-perf
Jun 5, 2026
Merged

fix: state parallel-region errors, evolution guarded-diff, expr int64, and hot-path allocations#150
joshua-temple merged 4 commits into
mainfrom
fix/state-correctness-perf

Conversation

@joshua-temple
Copy link
Copy Markdown
Collaborator

What this change does

Remediates the state-engine review findings (correctness + allocation-only perf + coverage; kernel purity preserved):

  • Parallel-region action errors (high): applyRegionTransition discarded runActions errors at its exit/transition/entry sites; each now propagates an *ActionFailedError mapped to OutcomeEffectError, matching the flat/compound commit path (with single- and multi-region tests).
  • expr int64 (high): the base map is decoded with json.UseNumber, so untouched int64 siblings above 2^53 survive a mergeUpdates.
  • evolution diff (high): guarded same-event branches are no longer collapsed by (from,on) (which hid breaking changes); multi-branch groups match by guard signature while a lone transition gaining a guard still reads as a guard change (not add+remove).
  • medium: analysis emits a KindDuplicateState finding instead of silently merging states that render to the same name; conformance enforces a scenario's declared InitialState; symbolic Overlaps iterates in first-seen order (determinism); expr adds the catalog entry before mutating the registry and checks its map[string]any assertion.
  • perf (allocation-only, semantics unchanged): matchingTransitions returns the single non-empty slice directly; activeParallelAncestor presizes its map; the effect label is built only in full-trace mode; Verify round-trips the IR once and threads it; the config graph caches its child index; expr gains a reusable CompileChecked.
  • coverage/docs: fireFromState branches, mergeTrace, typed Error/Unwrap, DiffMachines + evolution error types, Path.States, outcomeName (also fixed to render AssignFailed not Unknown), symbolic int literals; fixed the truncated analysis Step godoc.

Pushed back (with rationale): gating Trace.Event (a documented lite-mode field) and rewriting the verify BFS pop (standard idiom, near-zero gain) — both left as-is.

Checklist

  • Signed off (DCO), conventional commits; kernel purity/host-driven invariant preserved
  • Full consumer build+vet matrix green (workspace + GOWORK=off); consumer tests pass; state -race green; no consumer asserted the old swallow behavior

Parallel region transitions now surface a failing action as an
ActionFailedError classified OutcomeEffectError, matching the flat and
compound commit path instead of silently discarding the error. The expr
assign merge decodes the base context with json UseNumber so a large
int64 sibling field survives the round-trip exactly, and a rich
guard/assign records its catalog entry before mutating the registry so a
duplicate name no longer leaves a half-registered reducer behind.

Evolution Diff keys guarded sibling branches by their guard signature so
removing or retargeting one branch of a same-event fork is no longer
hidden, while a lone transition that gains or loses a guard still reads as
a guard change. Analysis surfaces a duplicate_state finding when two
declared states collide on their rendered name rather than silently
merging them. Conformance RunAgainst rejects a scenario whose declared
InitialState disagrees with the resolved start state. Symbolic Overlaps
iterates transition groups in first-seen order for deterministic output.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
matchingTransitions returns the specific or wildcard slice directly when
only one kind is present, so the steady-state bubble path no longer
allocates a merged slice. activeParallelAncestor presizes its scratch map
from the leaf count, and runActions builds the formatted effect label and
probes the comm microstep only in full trace mode, keeping the lite hot
path free of the Sprintf and effectLabel allocation.

Verify rounds the machine through its public IR once and threads it into
the topology, search-graph, and config-graph builders instead of
re-serializing per builder. The config graph caches its inverted child
index at build time so leavesUnder no longer rebuilds and re-sorts it on
every call. A new CompileChecked binds a stored rich AST to its
environment once for reuse across evaluations, with EvalCheckedAST now a
one-shot wrapper over it.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
Cover the fireFromState cross-cutting branches (commit, guard fail, guard
panic, forbidden, unhandled), the full-trace mergeTrace path through
FireSeq, the kernel typed Error and Unwrap methods, DiffMachines plus the
evolution Serialize/Decode error types, Path.States, the conformance
outcomeName branches, and the symbolic litNumber int forms.

conformance outcomeName now renders OutcomeAssignFailed as AssignFailed
instead of collapsing it to Unknown, so an assign failure stays distinct
in a scenario trace. The analysis Step godoc, previously truncated
mid-sentence, now describes the From/Event/To segment fully.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
readTopology and initialName became unused when the perf commit
threaded a single loadIR result through Verify's builders via the
FromIR variants. Remove both wrapper functions; update the two prose
comments in reach.go and invariant.go that named readTopology.

Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
@joshua-temple joshua-temple merged commit aa3bd9d into main Jun 5, 2026
121 checks passed
@joshua-temple joshua-temple deleted the fix/state-correctness-perf branch June 5, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant